<?php

/**
 * @desc		框架扩展：数据库操作类库|数据库资源池
 * ---------------------------------------------------------------------
 * @author	unphp <unphp@qq.com>
 * @date		2014-03-27
 * @copyright	UnPHP 1.1
 * ---------------------------------------------------------------------
 */
/* * *******************************
 *  配置如下

  [db]
  ;数据库映射
  taitong = taitong

  [taitong]
  ;数据库配置
  master.type = mysql
  master.host = 127.0.0.1
  master.port = 127.0.0.1
  master.username = 127.0.0.1
  master.password = 127.0.0.1
  master.charset = 127.0.0.1
  master.prefix = "tt"

  salve.type = mysql
  salve.host = 127.0.0.1
  salve.port = 127.0.0.1
  salve.username = 127.0.0.1
  salve.password = 127.0.0.1
  salve.charset = 127.0.0.1
  salve.prefix = "tt"

 * 
 * ********************************** */

namespace UnPHP\Lib\DBdriver;

//use DBPoolInterface;
//use DBPoolClientInterface;

class Pool implements DBPoolInterface
{

        private static $_instance = null;
        private $_dbconf          = array();
        private $_dbPool          = array();
        private $_modelReadPool   = array();
        private $_modelWritePool  = array();
        private $_beginPool       = array();
        private static $_error = array();
        private static $_sql = array();

        public function __construct($dbconf)
        {
                $this->_dbconf = $dbconf;
        }

        /**
         * 单例模式---实例自身
         * @return Pool
         */
        public static function instance($dbconf = null)
        {
                if (null === self::$_instance  &&  null !== $dbconf)
                {
                        self::$_instance = new self($dbconf);
                }
                return self::$_instance;
        }
        
        public static function throwError($error)
        {
                self::$_error[] = $error;
        }

        public static function getError()
        {
                return self::$_error;
        }

        public static function getSql()
        {
                return self::$_sql;;
        }

        public static function traceSql($sql)
        {
                self::$_sql[] = $sql;
        }

        /**
         * 
         * @param type $code
         * @param type $engineType
         * @param type $host
         * @param type $port
         * @param type $dbName
         * @param type $user
         * @param type $password
         */
        public function regReadPool($code, DBPoolClientInterface $client)
        {
                $this->_modelReadPool[$code] = $client;
        }

        /**
         * 
         * @param type $code
         * @param type $engineType
         * @param type $host
         * @param type $port
         * @param type $dbName
         * @param type $user
         * @param type $password
         */
        public function regWritePool($code, DBPoolClientInterface $client)
        {
                $this->_modelWritePool[$code] = $client;
        }

        /**
         * 
         * @param type $code
         * @return PoolClient
         */
        public function getReadPool($code)
        {
                if (isset($this->_beginPool[$code]))
                {
                        return $this->_beginPool[$code];
                }
                if (!isset($this->_modelReadPool[$code]))
                {
                        $this->regReadPool($code, $this->_getPoolClient($code, false));
                        //return false;
                }
                return $this->_modelReadPool[$code];
        }

        /**
         * 
         * @param type $code
         * @return PoolClient
         */
        public function getWritePool($code)
        {
                if (isset($this->_beginPool[$code]))
                {
                        return $this->_beginPool[$code];
                }

                if (!isset($this->_modelWritePool[$code]))
                {
                        $this->regWritePool($code, $this->_getPoolClient($code, true));
                        //return false;
                }
                return $this->_modelWritePool[$code];
        }

        /**
         * 
         * @param type $code
         * @return PoolClient
         */
        public function regBegin($code)
        {
                if (!isset($this->_beginPool[$code]))
                {
                        $poolClient = $this->getWritePool($code);
                        if (false === $poolClient)
                        {
                                return false;
                        }
                        $this->_beginPool[$code] = $poolClient;
                }
                return $this->_beginPool[$code];
        }

        /**
         * 
         * @param type $code
         * @return PoolClient
         */
        public function getBegin($code)
        {
                if (!isset($this->_beginPool[$code]))
                {
                        return false;
                }
                return $this->_beginPool[$code];
        }

        public function closeBegin($code)
        {
                if (!isset($this->_beginPool[$code]))
                {
                        return false;
                }
                unset($this->_beginPool[$code]);
        }

        private function _getPoolClient($code, $isMaster = true)
        {
                if (!isset($this->_dbconf['db']))
                {
                        throw new DBdriverException("数据库未配置！");
                }
                $dbCodeConf = $this->_dbconf['db'];
                if (!isset($dbCodeConf[$code]))
                {
                        throw new DBdriverException($code . "数据库未配置！");
                }
                $dbCode = $dbCodeConf[$code];
                $dbT    = $isMaster ? "master" : "salve";
                if (!isset($this->_dbconf[$dbCode]) || !isset($this->_dbconf[$dbCode][$dbT]))
                {
                        throw new DBdriverException($code . "数据库未配置！");
                }
                $dbConf     = $this->_dbconf[$dbCode][$dbT];
                $engineType = isset($dbConf['type']) ? $dbConf['type'] : 'mysql';
                $host       = $dbConf['host'];
                $port       = $dbConf['port'];
                $dbName     = $dbConf['dbname'];
                $user       = $dbConf['username'];
                $password   = $dbConf['password'];
                $md5        = md5($engineType . $host . $port . $dbName . $user . $password);
                if (!isset($this->_dbPool[$md5]))
                {
                        $charset             = isset($dbConf['charset']) ? $dbConf['charset'] : 'utf-8';
                        $prefix              = isset($dbConf['prefix']) ? $dbConf['prefix'] : null;
                        $client              = new PoolClient($host, $port, $dbName, $user, $password);
                        $client->setCharset($charset);
                        $client->setEngineType($engineType);
                        $client->setPrefix($prefix);
                        $this->_dbPool[$md5] = $client;
                }
                return $this->_dbPool[$md5];
        }

}
